import {Editor, EditorState, RichUtils, Modifier, genKey, ContentBlock, CharacterMetadata} from 'draft-js';


export function changeBlockType(editorState, blockKey, newType) {
  let content = editorState.getCurrentContent();
  let block = content.getBlockForKey(blockKey);
  let type = block.getType();
  if (type === newType) {
    return editorState;
  }
  let newBlock = block.set('type', newType);
  let newContent = content.merge({
    blockMap: content.getBlockMap().set(blockKey, newBlock)
  });

  return EditorState.push(
    editorState,
    newContent,
    'change-block-type'
  );
}

export function changeBlockDepth(editorState, blockKey, newDepth) {
  let content = editorState.getCurrentContent();
  let block = content.getBlockForKey(blockKey);
  let depth = block.getDepth();
  if (depth === newDepth) {
    return editorState;
  }
  let newBlock = block.set('depth', newDepth);
  let newContent = content.merge({
    blockMap: content.getBlockMap().set(blockKey, newBlock),
  });

  return EditorState.push(
    editorState,
    newContent,
    'adjust-depth'
  );
}

export function insertBlockAfter(editorState, blockKey, newType) {
  let content = editorState.getCurrentContent();
  let blockMap = content.getBlockMap();
  let block = blockMap.get(blockKey);
  let blocksBefore = blockMap.toSeq().takeUntil((v) => (v === block));
  let blocksAfter = blockMap.toSeq().skipUntil((v) => (v === block)).rest();
  let newBlockKey = genKey();
  let newBlock = new ContentBlock({
    key: newBlockKey,
    type: newType,
    text: '',
    characterList: block.getCharacterList().slice(0, 0),
    depth: 0,
  });
  let newBlockMap = blocksBefore.concat(
    [[blockKey, block], [newBlockKey, newBlock]],
    blocksAfter,
  ).toOrderedMap();
  let selection = editorState.getSelection();
  let newContent = content.merge({
    blockMap: newBlockMap,
    selectionBefore: selection,
    selectionAfter: selection.merge({
      anchorKey: newBlockKey,
      anchorOffset: 0,
      focusKey: newBlockKey,
      focusOffset: 0,
      isBackward: false
    })
  });
  return EditorState.push(editorState, newContent, 'split-block');
}


function getEntityAtOffset(block, offset) {
  let entityKey = block.getEntityAt(offset);
  if (entityKey == null) {
    return null;
  }
  let startOffset = offset;
  while (startOffset > 0 && block.getEntityAt(startOffset - 1) === entityKey) {
    startOffset -= 1;
  }
  let endOffset = startOffset;
  let blockLength = block.getLength();
  while (endOffset < blockLength && block.getEntityAt(endOffset + 1) === entityKey) {
    endOffset += 1;
  }
  return {
    entityKey,
    blockKey: block.getKey(),
    startOffset,
    endOffset: endOffset + 1
  };
}

export function getEntityAtCursor(editorState) {
  let selection = editorState.getSelection();
  let startKey = selection.getStartKey();
  let startBlock = editorState.getCurrentContent().getBlockForKey(startKey);
  let startOffset = selection.getStartOffset();
  if (selection.isCollapsed()) {
    // Get the entity before the cursor (unless the cursor is at the start).
    return getEntityAtOffset(startBlock, startOffset === 0 ? startOffset : startOffset - 1);
  }
  if (startKey !== selection.getEndKey()) {
    return null;
  }
  let endOffset = selection.getEndOffset();
  let startEntityKey = startBlock.getEntityAt(startOffset);
  for (let i = startOffset; i < endOffset; i++) {
    let entityKey = startBlock.getEntityAt(i);
    if (entityKey == null || entityKey !== startEntityKey) {
      return null;
    }
  }
  return {
    entityKey: startEntityKey,
    blockKey: startBlock.getKey(),
    startOffset: startOffset,
    endOffset: endOffset,
  };
}

export function clearEntityForRange(editorState, blockKey, startOffset, endOffset): EditorState {
  let contentState = editorState.getCurrentContent();
  let blockMap = contentState.getBlockMap();
  let block = blockMap.get(blockKey);
  let charList = block.getCharacterList();
  let newCharList = charList.map((char, i) => {
    if (i >= startOffset && i < endOffset) {
      return CharacterMetadata.applyEntity(char, null);
    } else {
      return char;
    }
  });
  let newBlock = block.set('characterList', newCharList);
  let newBlockMap = blockMap.set(blockKey, newBlock);
  let newContentState = contentState.set('blockMap', newBlockMap);
  return EditorState.push(editorState, newContentState, 'apply-entity');
}
